#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""统一媒体文件（图片）保存与访问路径服务。

目标：
1. 数据库存储统一使用相对URL: /media/<category>/<filename>
2. 物理存储：<MEDIA_ROOT>/<category>/<filename>
3. 仅在需要时前端拼接域名；代码不写死 http://localhost
"""
import os
import uuid
from datetime import datetime
from typing import Tuple
from flask import current_app

class MediaService:
    @staticmethod
    def ensure_category(category: str) -> str:
        if not category:
            raise ValueError("category 不能为空")
        category = category.strip().lower()
        return category

    @staticmethod
    def generate_filename(orig_name: str) -> str:
        ext = ''
        if '.' in orig_name:
            ext = orig_name.rsplit('.', 1)[1].lower()
        return f"{datetime.now().strftime('%Y%m%d_%H%M%S')}_{uuid.uuid4().hex[:8]}{'.'+ext if ext else ''}"

    @staticmethod
    def save_image(file_storage, category: str) -> Tuple[str, str]:
        """保存上传图片并返回(相对URL, 物理路径)
        目录结构: <MEDIA_ROOT>/image/<category>/YYYY/MM/DD/filename
        URL: /media/image/<category>/YYYY/MM/DD/filename
        """
        cfg = current_app.config
        category = MediaService.ensure_category(category)
        media_root = cfg.get('MEDIA_ROOT')
        today = datetime.now()
        rel_dir_parts = ['image', category, today.strftime('%Y'), today.strftime('%m'), today.strftime('%d')]
        rel_dir = os.path.join(*rel_dir_parts)
        full_dir = os.path.join(media_root, rel_dir)
        os.makedirs(full_dir, exist_ok=True)
        filename = MediaService.generate_filename(file_storage.filename)
        physical_path = os.path.join(full_dir, filename)
        file_storage.save(physical_path)
        relative_url = f"{cfg.get('MEDIA_URL', '/media')}/" + "/".join(rel_dir_parts) + f"/{filename}"
        return relative_url, physical_path

    @staticmethod
    def physical_path_from_url(relative_url: str) -> str:
        cfg = current_app.config
        media_root = cfg.get('MEDIA_ROOT')
        media_url = cfg.get('MEDIA_URL', '/media')
        if relative_url.startswith(media_url):
            rel_part = relative_url[len(media_url):].lstrip('/')
            return os.path.join(media_root, rel_part.replace('/', os.sep))
        # 如果不是标准前缀，直接拼接（降级）
        return os.path.join(media_root, relative_url.lstrip('/'))
